/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_variables,
    clippy::never_loop
)]
use crate::common::*;
extern "C" {
    fn fstat(filedes:libc::c_int,buf:*mut stat) -> libc::c_int;
    fn snprintf(
        _: *mut libc::c_char,
        _: libc::c_ulong,
        _: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void;
    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn __ctype_b_loc() -> *mut *const libc::c_ushort;
    fn time(__timer: *mut time_t) -> time_t;
    fn strftime(
        __s: *mut libc::c_char,
        __maxsize: size_t,
        __format: *const libc::c_char,
        __tp: *const tm,
    ) -> size_t;
    fn gmtime(__timer: *const time_t) -> *mut tm;
    fn cmnd_matches(parse_tree: *mut sudoers_parse_tree, m: *const member) -> libc::c_int;
    fn hostlist_matches(
        parse_tree: *mut sudoers_parse_tree,
        pw: *const passwd,
        list: *const member_list,
    ) -> libc::c_int;
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn update_defaults(
        parse_tree: *mut sudoers_parse_tree,
        defs: *mut defaults_list,
        what: libc::c_int,
        quiet: bool,
    ) -> bool;
    static mut sudo_defs_table: [sudo_defs_types; 0];
    fn runaslist_matches(
        parse_tree: *mut sudoers_parse_tree,
        user_list: *const member_list,
        group_list: *const member_list,
        matching_user: *mut *mut member,
        matching_group: *mut *mut member,
    ) -> libc::c_int;
    fn userlist_matches(
        parse_tree: *mut sudoers_parse_tree,
        pw: *const passwd,
        list: *const member_list,
    ) -> libc::c_int;
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn restore_perms() -> bool;
    static mut sudo_user: sudo_user;
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    fn sudo_debug_enter_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
    );
    fn sudo_nss_can_continue(nss: *mut sudo_nss, match_0: libc::c_int) -> bool;
    fn sudo_pw_addref(_: *mut passwd);
    fn sudo_pw_delref(_: *mut passwd);
    fn set_perms(_: libc::c_int) -> bool;
    static mut list_pw: *mut passwd;
    fn sudoers_format_cmndspec(
        lbuf: *mut sudo_lbuf,
        parse_tree: *mut sudoers_parse_tree,
        cs: *mut cmndspec,
        prev_cs: *mut cmndspec,
        tags: cmndtag,
        expand_aliases: bool,
    ) -> bool;
    fn sudoers_format_member(
        lbuf: *mut sudo_lbuf,
        parse_tree: *mut sudoers_parse_tree,
        m: *mut member,
        separator: *const libc::c_char,
        alias_type: libc::c_int,
    ) -> bool;
    fn dcgettext(
        __domainname: *const libc::c_char,
        __msgid: *const libc::c_char,
        __category: libc::c_int,
    ) -> *mut libc::c_char;
    fn sudoers_defaults_list_to_tags(defs: *mut defaults_list, tags: *mut cmndtag) -> bool;
    fn sudoers_format_default(lbuf: *mut sudo_lbuf, d: *mut defaults) -> bool;
    static mut sudo_conv: sudo_conv_t;
    static mut sudo_printf:
        Option<unsafe extern "C" fn(libc::c_int, *const libc::c_char, ...) -> libc::c_int>;
    fn sudo_lbuf_init_v1(
        lbuf: *mut sudo_lbuf,
        output_0: sudo_lbuf_output_t,
        indent: libc::c_int,
        continuation: *const libc::c_char,
        cols: libc::c_int,
    );
    fn sudo_lbuf_destroy_v1(lbuf: *mut sudo_lbuf);
    fn sudo_lbuf_append_v1(lbuf: *mut sudo_lbuf, fmt: *const libc::c_char, _: ...) -> bool;
    fn sudo_lbuf_print_v1(lbuf: *mut sudo_lbuf);
    fn sudo_lbuf_error_v1(lbuf: *mut sudo_lbuf) -> bool;
}

pub const FLAG_NO_CHECK: libc::c_int = 0x080;
pub const FLAG_NO_USER: libc::c_int = 0x020;
pub const FLAG_NO_HOST: libc::c_int = 0x040;
pub const DENY: libc::c_int = 0;
pub const VALIDATE_ERROR: libc::c_int = 0x001;
pub const ALLOW: libc::c_int = 1;
pub const VALIDATE_SUCCESS: libc::c_int = 0x002;
pub const VALIDATE_FAILURE: libc::c_int = 0x004;
pub const FLAG_CHECK_USER: libc::c_int = 0x010;
pub const PERM_RUNAS: libc::c_int = 0x05;
pub const SETDEF_GENERIC: libc::c_int = 0x01;
pub const DEFAULTS_CMND: libc::c_int = 269;
pub const DEFAULTS_RUNAS: libc::c_int = 268;
pub const DEFAULTS_USER: libc::c_int = 267;
pub const DEFAULTS_HOST: libc::c_int = 266;
pub const STDOUT_FILENO: libc::c_int = 1;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_nss {
    pub entries: C2RustUnnamed_7,
    pub open: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub close: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub parse: Option<unsafe extern "C" fn(*mut sudo_nss) -> *mut sudoers_parse_tree>,
    pub query: Option<unsafe extern "C" fn(*mut sudo_nss, *mut passwd) -> libc::c_int>,
    pub getdefs: Option<unsafe extern "C" fn(*mut sudo_nss) -> libc::c_int>,
    pub handle: *mut libc::c_void,
    pub parse_tree: *mut sudoers_parse_tree,
    pub ret_if_found: bool,
    pub ret_if_notfound: bool,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct C2RustUnnamed_7 {
    pub tqe_next: *mut sudo_nss,
    pub tqe_prev: *mut *mut sudo_nss,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct sudo_nss_list {
    pub tqh_first: *mut sudo_nss,
    pub tqh_last: *mut *mut sudo_nss,
}
pub type sudo_lbuf_output_t = Option<unsafe extern "C" fn(*const libc::c_char) -> libc::c_int>;

fn sudoers_lookup_pseudo(
    mut snl: *mut sudo_nss_list,
    mut pw: *mut passwd,
    mut validated: libc::c_int,
    mut pwflag: libc::c_int,
) -> libc::c_int {
    let mut match_0: libc::c_int = 0;
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
    let mut priv_0: *mut privilege = std::ptr::null_mut::<privilege>();
    let mut us: *mut userspec = std::ptr::null_mut::<userspec>();
    let mut def: *mut defaults = std::ptr::null_mut::<defaults>();
    let mut nopass: libc::c_int = 0;
    let mut pwcheck: libc::c_uint = def_tuple::never as libc::c_uint;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        pwcheck = if pwflag == -(1 as libc::c_int) {
            def_tuple::never as libc::c_uint
        } else {
            (*sudo_defs_table.as_mut_ptr().offset(pwflag as isize))
                .sd_un
                .tuple as libc::c_uint
        };
        nopass = if pwcheck as libc::c_uint == def_tuple::never as libc::c_int as libc::c_uint
            || pwcheck as libc::c_uint == def_tuple::all as libc::c_int as libc::c_uint
        {
            true as libc::c_int
        } else {
            false as libc::c_int
        };

        if list_pw.is_null() {
            SET!(validated, FLAG_NO_CHECK);
        }
        CLR!(validated, FLAG_NO_USER);
        CLR!(validated, FLAG_NO_HOST);
        match_0 = DENY;
        nss = (*snl).tqh_first;
        while !nss.is_null() {
            if ((*nss).query).expect("non-null function pointer")(nss, pw) == -(1 as libc::c_int) {
                /* The query function should have printed an error message. */
                SET!(validated, VALIDATE_ERROR);
                break;
            } else {
                us = (*(*nss).parse_tree).userspecs.tqh_first;
                while !us.is_null() {
                    if userlist_matches((*nss).parse_tree, pw, &(*us).users) == ALLOW {
                        priv_0 = (*us).privileges.tqh_first;
                        while !priv_0.is_null() {
                            let mut priv_nopass: libc::c_int = UNSPEC;

                            if hostlist_matches((*nss).parse_tree, pw, &(*priv_0).hostlist) == ALLOW
                            {
                                def = (*priv_0).defaults.tqh_first;
                                while !def.is_null() {
                                    if strcmp(
                                        (*def).var,
                                        b"authenticate\0" as *const u8 as *const libc::c_char,
                                    ) == 0 as libc::c_int
                                    {
                                        priv_nopass = ((*def).op == 0) as libc::c_int;
                                    }
                                    def = (*def).entries.tqe_next;
                                }
                                cs = (*priv_0).cmndlist.tqh_first;
                                while !cs.is_null() {
                                    if pwcheck as libc::c_uint
                                        == def_tuple::any as libc::c_int as libc::c_uint
                                    {
                                        if ((*cs).tags).nopasswd() == true as libc::c_int
                                            || priv_nopass == true as libc::c_int
                                        {
                                            nopass = true as libc::c_int;
                                        }
                                    } else if pwcheck as libc::c_uint
                                        == def_tuple::all as libc::c_int as libc::c_uint
                                        && ((*cs).tags).nopasswd() != true as libc::c_int
                                        && priv_nopass != true as libc::c_int
                                    {
                                        nopass = false as libc::c_int;
                                    }

                                    /*} else if pwcheck as libc::c_uint
                                        == def_tuple::all as libc::c_int as libc::c_uint
                                    {
                                        if ((*cs).tags).nopasswd() != true as libc::c_int
                                            && priv_nopass != true as libc::c_int
                                        {
                                            nopass = false as libc::c_int;
                                        }
                                    }*/
                                    if match_0 != ALLOW {
                                        /* Only check the command when listing another user. */
                                        if sudo_user.uid == 0 as libc::c_int as libc::c_uint
                                            || list_pw.is_null()
                                            || sudo_user.uid == (*list_pw).pw_uid
                                            || cmnd_matches((*nss).parse_tree, (*cs).cmnd) == ALLOW
                                        {
                                            match_0 = ALLOW;
                                        }
                                    }
                                    cs = (*cs).entries.tqe_next;
                                }
                            }
                            priv_0 = (*priv_0).entries.tqe_next;
                        }
                    }
                    us = (*us).entries.tqe_next;
                }
                nss = (*nss).entries.tqe_next;
            }
        }
        if match_0 == ALLOW || sudo_user.uid == 0 as libc::c_int as libc::c_uint {
            /* User has an entry for this host. */
            SET!(validated, VALIDATE_SUCCESS);
        } else if match_0 == DENY {
            SET!(validated, VALIDATE_FAILURE);
        }
        if pwcheck == def_tuple::always as libc::c_uint && def_authenticate!() != 0 {
            SET!(validated, FLAG_CHECK_USER);
        } else if nopass == true as libc::c_int {
            def_authenticate!() = false as libc::c_int;
        }
        debug_return_int!(validated);
    } //unsafe
}

fn sudoers_lookup_check(
    mut nss: *mut sudo_nss,
    mut pw: *mut passwd,
    mut validated: *mut libc::c_int,
    mut matching_cs: *mut *mut cmndspec,
    mut defs: *mut *mut defaults_list,
    mut now: time_t,
) -> libc::c_int {
    let mut host_match: libc::c_int = 0;
    let mut runas_match: libc::c_int = 0;
    let mut cmnd_match: libc::c_int = 0;
    let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
    let mut priv_0: *mut privilege = std::ptr::null_mut::<privilege>();
    let mut us: *mut userspec = std::ptr::null_mut::<userspec>();
    let mut matching_user: *mut member = std::ptr::null_mut::<member>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        us = *(*((*(*nss).parse_tree).userspecs.tqh_last as *mut userspec_list)).tqh_last;
        while !us.is_null() {
            if userlist_matches((*nss).parse_tree, pw, &(*us).users) != ALLOW {
                us = *(*((*us).entries.tqe_prev as *mut userspec_list)).tqh_last;
                continue;
            }
            CLR!(*validated, FLAG_NO_USER);
            priv_0 = *(*((*us).privileges.tqh_last as *mut privilege_list)).tqh_last;
            while !priv_0.is_null() {
                host_match = hostlist_matches((*nss).parse_tree, pw, &(*priv_0).hostlist);
                if host_match == ALLOW {
                    CLR!(*validated, FLAG_NO_HOST);
                } else {
                    priv_0 = *(*((*priv_0).entries.tqe_prev as *mut privilege_list)).tqh_last;
                    continue;
                }
                cs = *(*((*priv_0).cmndlist.tqh_last as *mut cmndspec_list)).tqh_last;
                while !cs.is_null() {
                    if (*cs).notbefore != UNSPEC as libc::c_long && now < (*cs).notbefore {
                        cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                        continue;
                    }
                    /*if (*cs).notbefore != UNSPEC as libc::c_long {
                        if now < (*cs).notbefore {
                            cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                            continue;
                        }
                    }*/
                    if (*cs).notafter != UNSPEC as libc::c_long && now > (*cs).notafter {
                        cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                        continue;
                    }

                    /*if (*cs).notafter != UNSPEC as libc::c_long {
                        if now > (*cs).notafter {
                            cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                            continue;
                        }
                    }*/
                    matching_user = std::ptr::null_mut::<member>();
                    runas_match = runaslist_matches(
                        (*nss).parse_tree,
                        (*cs).runasuserlist,
                        (*cs).runasgrouplist,
                        &mut matching_user,
                        std::ptr::null_mut::<*mut member>(),
                    );
                    if runas_match == ALLOW {
                        cmnd_match = cmnd_matches((*nss).parse_tree, (*cs).cmnd);
                        if cmnd_match != UNSPEC {
                            /*
                             * If user is running command as himself,
                             * set runas_pw = sudo_user.pw.
                             * XXX - hack, want more general solution
                             */
                            if !matching_user.is_null()
                                && (*matching_user).type0 as libc::c_int == MYSELF
                            {
                                sudo_pw_delref(sudo_user._runas_pw);
                                sudo_pw_addref(sudo_user.pw);
                                sudo_user._runas_pw = sudo_user.pw;
                            }
                            *matching_cs = cs;
                            *defs = &mut (*priv_0).defaults;
                            sudo_debug_printf!(
                                SUDO_DEBUG_DEBUG | SUDO_DEBUG_LINENO,
                                b"userspec matched @ %s:%d %s\0" as *const u8
                                    as *const libc::c_char,
                                (*us).file,
                                (*us).lineno,
                                if cmnd_match != 0 {
                                    b"allowed\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"denied\0" as *const u8 as *const libc::c_char
                                }
                            );
                            debug_return_int!(cmnd_match);
                        }
                    }

                    cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                }

                priv_0 = *(*((*priv_0).entries.tqe_prev as *mut privilege_list)).tqh_last;
            }

            us = *(*((*us).entries.tqe_prev as *mut userspec_list)).tqh_last;
        }

        debug_return_int!(UNSPEC);
    } //unsafe
}

/*
 * Apply cmndspec-specific settngs including SELinux role/type,
 * Solaris privs, and command tags.
 */
fn apply_cmndspec(mut cs: *mut cmndspec) -> bool {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        if !cs.is_null() {
            /* Set role and type if not specified on command line. */
            if user_role!().is_null() {
                if !((*cs).role).is_null() {
                    user_role!() = strdup((*cs).role);
                    if user_role!().is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        debug_return_bool!(false);
                    }
                } else {
                    user_role!() = def_role!();
                }
            }
            if (sudo_user.type_0).is_null() {
                if !((*cs).type_0).is_null() {
                    sudo_user.type_0 = strdup((*cs).type_0);
                    if (sudo_user.type_0).is_null() {
                        sudo_warnx!(
                            b"%s: %s\0" as *const u8 as *const libc::c_char,
                            get_function_name!(),
                            b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                        );
                        debug_return_bool!(false);
                    }
                } else {
                    user_type!() = def_type!();
                }
            }
            if (*cs).timeout > 0 as libc::c_int {
                def_command_timeout!() = (*cs).timeout;
            }
            if ((*cs).tags).nopasswd() != UNSPEC {
                def_authenticate!() = (((*cs).tags).nopasswd() == 0) as libc::c_int;
            }
            if ((*cs).tags).noexec() != UNSPEC {
                def_noexec!() = ((*cs).tags).noexec();
            }
            if ((*cs).tags).setenv() != UNSPEC {
                def_setenv!() = ((*cs).tags).setenv();
            }
            if ((*cs).tags).log_input() != UNSPEC {
                def_log_input!() = ((*cs).tags).log_input();
            }
            if ((*cs).tags).log_output() != UNSPEC {
                def_log_output!() = ((*cs).tags).log_output()
            }
            if ((*cs).tags).send_mail() != UNSPEC {
                if ((*cs).tags).send_mail() != 0 {
                    def_mail_all_cmnds!() = true as libc::c_int;
                } else {
                    def_mail_all_cmnds!() = false as libc::c_int;
                    def_mail_always!() = false as libc::c_int;
                    def_mail_no_perms!() = false as libc::c_int;
                }
            }
            if ((*cs).tags).follow() != UNSPEC {
                def_sudoedit_follow!() = ((*cs).tags).follow();
            }
        }

        debug_return_bool!(true);
    } //unsafe
}

/*
 * Look up the user in the sudoers parse tree and check to see if they are
 * allowed to run the specified command on this host as the target user.
 */
#[no_mangle]
pub fn sudoers_lookup(
    mut snl: *mut sudo_nss_list,
    mut pw: *mut passwd,
    mut validated: libc::c_int,
    mut pwflag: libc::c_int,
) -> libc::c_int {
    let mut defs: *mut defaults_list = std::ptr::null_mut::<defaults_list>();
    let mut parse_tree: *mut sudoers_parse_tree = std::ptr::null_mut::<sudoers_parse_tree>();
    let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut m: libc::c_int = 0;
    let mut match_0: libc::c_int = -(1 as libc::c_int);
    let mut now: time_t = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        /*
         * Special case checking the "validate", "list" and "kill" pseudo-commands.
         */
        if pwflag != 0 {
            debug_return_int!(sudoers_lookup_pseudo(snl, pw, validated, pwflag));
        }

        /* Need to be runas user while stat'ing things. */
        if !set_perms(PERM_RUNAS) {
            debug_return_int!(validated)
        }

        /* Query each sudoers source and check the user. */
        time(&mut now);
        nss = (*snl).tqh_first;
        while !nss.is_null() {
            if ((*nss).query).expect("non-null function pointer")(nss, pw) == -(1 as libc::c_int) {
                /* The query function should have printed an error message. */
                SET!(validated, VALIDATE_ERROR);
                break;
            }

            m = sudoers_lookup_check(nss, pw, &mut validated, &mut cs, &mut defs, now);
            if m != UNSPEC {
                match_0 = m;
                parse_tree = (*nss).parse_tree;
            }

            if !sudo_nss_can_continue(nss, m) {
                break;
            }
            nss = (*nss).entries.tqe_next;
        }
        if match_0 != UNSPEC {
            if !defs.is_null() {
                update_defaults(parse_tree, defs, SETDEF_GENERIC, false);
            }
            if !apply_cmndspec(cs) {
                SET!(validated, VALIDATE_ERROR);
            } else if match_0 == ALLOW {
                SET!(validated, VALIDATE_SUCCESS);
            } else {
                SET!(validated, VALIDATE_FAILURE);
            }
        }
        if !restore_perms() {
            SET!(validated, VALIDATE_ERROR);
        }
        debug_return_int!(validated);
    } //unsafe
}

fn display_priv_short(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut us: *mut userspec,
    mut lbuf: *mut sudo_lbuf,
) -> libc::c_int {
    let mut priv_0: *mut privilege = std::ptr::null_mut::<privilege>();
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        priv_0 = (*us).privileges.tqh_first;
        while !priv_0.is_null() {
            let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
            let mut prev_cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
            let mut tags: cmndtag = cmndtag {
                nopasswd_noexec_setenv_log_input_log_output_send_mail_follow: [0; 3],
                c2rust_padding: [0; 1],
            };

            if hostlist_matches(parse_tree, pw, &(*priv_0).hostlist) == ALLOW {
                sudoers_defaults_list_to_tags(&mut (*priv_0).defaults, &mut tags);
                cs = (*priv_0).cmndlist.tqh_first;
                while !cs.is_null() {
                    /* Start a new line if RunAs changes. */
                    if prev_cs.is_null() || RUNAS_CHANGED!(cs, prev_cs) {
                        let mut m: *mut member = std::ptr::null_mut::<member>();

                        if cs != (*priv_0).cmndlist.tqh_first {
                            sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                        }
                        sudo_lbuf_append_v1(lbuf, b"    (\0" as *const u8 as *const libc::c_char);
                        if !((*cs).runasuserlist).is_null() {
                            m = (*(*cs).runasuserlist).tqh_first;
                            while !m.is_null() {
                                if m != (*(*cs).runasuserlist).tqh_first {
                                    sudo_lbuf_append_v1(
                                        lbuf,
                                        b", \0" as *const u8 as *const libc::c_char,
                                    );
                                }
                                sudoers_format_member(
                                    lbuf,
                                    parse_tree,
                                    m,
                                    b", \0" as *const u8 as *const libc::c_char,
                                    RUNASALIAS,
                                );
                                m = (*m).entries.tqe_next;
                            }
                        } else if ((*cs).runasgrouplist).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%s\0" as *const u8 as *const libc::c_char,
                                def_runas_default!(),
                            );
                        } else {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%s\0" as *const u8 as *const libc::c_char,
                                (*pw).pw_name,
                            );
                        }
                        if !((*cs).runasgrouplist).is_null() {
                            sudo_lbuf_append_v1(lbuf, b" : \0" as *const u8 as *const libc::c_char);
                            m = (*(*cs).runasgrouplist).tqh_first;
                            while !m.is_null() {
                                if m != (*(*cs).runasgrouplist).tqh_first {
                                    sudo_lbuf_append_v1(
                                        lbuf,
                                        b", \0" as *const u8 as *const libc::c_char,
                                    );
                                }
                                sudoers_format_member(
                                    lbuf,
                                    parse_tree,
                                    m,
                                    b", \0" as *const u8 as *const libc::c_char,
                                    RUNASALIAS,
                                );
                                m = (*m).entries.tqe_next;
                            }
                        }
                        sudo_lbuf_append_v1(lbuf, b") \0" as *const u8 as *const libc::c_char);
                    } else if cs != (*priv_0).cmndlist.tqh_first {
                        sudo_lbuf_append_v1(lbuf, b", \0" as *const u8 as *const libc::c_char);
                    }
                    sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, tags, true);
                    prev_cs = cs;
                    nfound += 1;
                    cs = (*cs).entries.tqe_next;
                }
                sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
            }
            priv_0 = (*priv_0).entries.tqe_next;
        }

        debug_return_int!(nfound);
    } //unsafe
}

/*
 * Compare the current cmndspec with the previous one to determine
 * whether we need to start a new long entry for "sudo -ll".
 * Returns true if we should start a new long entry, else false.
 */
fn new_long_entry(mut cs: *mut cmndspec, mut prev_cs: *mut cmndspec) -> bool {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        if prev_cs.is_null() {
            debug_return_bool!(true);
        }
        if RUNAS_CHANGED!(cs, prev_cs) || TAGS_CHANGED!((*prev_cs).tags, (*cs).tags) {
            debug_return_bool!(true);
        }
        if !((*cs).role).is_null()
            && (((*prev_cs).role).is_null()
                || strcmp((*cs).role, (*prev_cs).role) != 0 as libc::c_int)
        {
            debug_return_bool!(true);
        }
        if !((*cs).type_0).is_null()
            && (((*prev_cs).type_0).is_null()
                || strcmp((*cs).type_0, (*prev_cs).type_0) != 0 as libc::c_int)
        {
            debug_return_bool!(true);
        }
        if (*cs).timeout != (*prev_cs).timeout {
            debug_return_bool!(true);
        }
        if (*cs).notbefore != (*prev_cs).notbefore {
            debug_return_bool!(true);
        }
        if (*cs).notafter != (*prev_cs).notafter {
            debug_return_bool!(true);
        }
        debug_return_bool!(false);
    } //unsafe
}

fn display_priv_long(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut us: *mut userspec,
    mut lbuf: *mut sudo_lbuf,
) -> libc::c_int {
    let mut priv_0: *mut privilege = std::ptr::null_mut::<privilege>();
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        priv_0 = (*us).privileges.tqh_first;
        while !priv_0.is_null() {
            let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
            let mut prev_cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();

            if hostlist_matches(parse_tree, pw, &(*priv_0).hostlist) == 1 as libc::c_int {
                prev_cs = std::ptr::null_mut::<cmndspec>();
                cs = (*priv_0).cmndlist.tqh_first;
                while !cs.is_null() {
                    let mut d: *mut defaults = std::ptr::null_mut::<defaults>();
                    let mut m: *mut member = std::ptr::null_mut::<member>();

                    if new_long_entry(cs, prev_cs) {
                        let mut olen: libc::c_int = 0;

                        if !((*priv_0).ldap_role).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                dcgettext(
                                    b"sudoers\0" as *const u8 as *const libc::c_char,
                                    b"\nLDAP Role: %s\n\0" as *const u8 as *const libc::c_char,
                                    5 as libc::c_int,
                                ),
                                (*priv_0).ldap_role,
                            );
                        } else {
                            sudo_lbuf_append_v1(
                                lbuf,
                                dcgettext(
                                    b"sudoers\0" as *const u8 as *const libc::c_char,
                                    b"\nSudoers entry:\n\0" as *const u8 as *const libc::c_char,
                                    5 as libc::c_int,
                                ),
                            );
                        }
                        sudo_lbuf_append_v1(
                            lbuf,
                            dcgettext(
                                b"sudoers\0" as *const u8 as *const libc::c_char,
                                b"    RunAsUsers: \0" as *const u8 as *const libc::c_char,
                                5 as libc::c_int,
                            ),
                        );
                        if !((*cs).runasuserlist).is_null() {
                            m = (*(*cs).runasuserlist).tqh_first;
                            while !m.is_null() {
                                if m != (*(*cs).runasuserlist).tqh_first {
                                    sudo_lbuf_append_v1(
                                        lbuf,
                                        b", \0" as *const u8 as *const libc::c_char,
                                    );
                                }
                                sudoers_format_member(
                                    lbuf,
                                    parse_tree,
                                    m,
                                    b", \0" as *const u8 as *const libc::c_char,
                                    RUNASALIAS,
                                );
                                m = (*m).entries.tqe_next;
                            }
                        } else if ((*cs).runasgrouplist).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%s\0" as *const u8 as *const libc::c_char,
                                def_runas_default!(),
                            );
                        } else {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%s\0" as *const u8 as *const libc::c_char,
                                (*pw).pw_name,
                            );
                        }
                        sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                        if !((*cs).runasgrouplist).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                dcgettext(
                                    b"sudoers\0" as *const u8 as *const libc::c_char,
                                    b"    RunAsGroups: \0" as *const u8 as *const libc::c_char,
                                    5 as libc::c_int,
                                ),
                            );
                            m = (*(*cs).runasgrouplist).tqh_first;
                            while !m.is_null() {
                                if m != (*(*cs).runasgrouplist).tqh_first {
                                    sudo_lbuf_append_v1(
                                        lbuf,
                                        b", \0" as *const u8 as *const libc::c_char,
                                    );
                                }
                                sudoers_format_member(
                                    lbuf,
                                    parse_tree,
                                    m,
                                    b", \0" as *const u8 as *const libc::c_char,
                                    RUNASALIAS,
                                );
                                m = (*m).entries.tqe_next;
                            }
                            sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                        }
                        olen = (*lbuf).len;
                        sudo_lbuf_append_v1(
                            lbuf,
                            dcgettext(
                                b"sudoers\0" as *const u8 as *const libc::c_char,
                                b"    Options: \0" as *const u8 as *const libc::c_char,
                                5 as libc::c_int,
                            ),
                        );
                        d = (*priv_0).defaults.tqh_first;
                        while !d.is_null() {
                            sudoers_format_default(lbuf, d);
                            sudo_lbuf_append_v1(lbuf, b", \0" as *const u8 as *const libc::c_char);
                            d = (*d).entries.tqe_next;
                        }
                        if TAG_SET!(((*cs).tags).setenv()) {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%ssetenv, \0" as *const u8 as *const libc::c_char,
                                if ((*cs).tags).setenv() != 0 {
                                    b"\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"!\0" as *const u8 as *const libc::c_char
                                },
                            );
                        }
                        if TAG_SET!(((*cs).tags).noexec()) {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%snoexec, \0" as *const u8 as *const libc::c_char,
                                if ((*cs).tags).noexec() != 0 {
                                    b"\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"!\0" as *const u8 as *const libc::c_char
                                },
                            );
                        }
                        if TAG_SET!(((*cs).tags).nopasswd()) {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%sauthenticate, \0" as *const u8 as *const libc::c_char,
                                if ((*cs).tags).nopasswd() != 0 {
                                    b"\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"!\0" as *const u8 as *const libc::c_char
                                },
                            );
                        }
                        if TAG_SET!(((*cs).tags).log_input()) {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%slog_input, \0" as *const u8 as *const libc::c_char,
                                if ((*cs).tags).log_input() != 0 {
                                    b"\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"!\0" as *const u8 as *const libc::c_char
                                },
                            );
                        }
                        if TAG_SET!(((*cs).tags).log_output()) {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"%slog_output, \0" as *const u8 as *const libc::c_char,
                                if ((*cs).tags).log_output() != 0 {
                                    b"\0" as *const u8 as *const libc::c_char
                                } else {
                                    b"!\0" as *const u8 as *const libc::c_char
                                },
                            );
                        }
                        if *((*lbuf).buf).offset(((*lbuf).len - 2 as libc::c_int) as isize)
                            as libc::c_int
                            == ',' as i32
                        {
                            (*lbuf).len -= 2 as libc::c_int; /* remove trailing ", " */
                            sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                        } else {
                            (*lbuf).len = olen; /* no options */
                        }
                        if !((*cs).role).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"    Role: %s\n\0" as *const u8 as *const libc::c_char,
                                (*cs).role,
                            );
                        }
                        if !((*cs).type_0).is_null() {
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"    Type: %s\n\0" as *const u8 as *const libc::c_char,
                                (*cs).type_0,
                            );
                        }
                        if (*cs).timeout > 0 as libc::c_int {
                            let mut numbuf: [libc::c_char; 13] = [0; 13];
                            snprintf(
                                numbuf.as_mut_ptr(),
                                ::core::mem::size_of::<[libc::c_char; 13]>() as libc::c_ulong,
                                b"%d\0" as *const u8 as *const libc::c_char,
                                (*cs).timeout,
                            );
                            sudo_lbuf_append_v1(
                                lbuf,
                                b"    Timeout: %s\n\0" as *const u8 as *const libc::c_char,
                                numbuf.as_mut_ptr(),
                            );
                        }
                        if (*cs).notbefore != UNSPEC as libc::c_long {
                            let mut buf: [libc::c_char; 16] = [0; 16];
                            let mut tm: *mut tm = gmtime(&(*cs).notbefore);
                            if strftime(
                                buf.as_mut_ptr(),
                                ::core::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
                                b"%Y%m%d%H%M%SZ\0" as *const u8 as *const libc::c_char,
                                tm,
                            ) != 0 as libc::c_int as libc::c_ulong
                            {
                                sudo_lbuf_append_v1(
                                    lbuf,
                                    b"    NotBefore: %s\n\0" as *const u8 as *const libc::c_char,
                                    buf.as_mut_ptr(),
                                );
                            }
                        }
                        if (*cs).notafter != UNSPEC as libc::c_long {
                            let mut buf_0: [libc::c_char; 16] = [0; 16];
                            let mut tm_0: *mut tm = gmtime(&(*cs).notafter);
                            if strftime(
                                buf_0.as_mut_ptr(),
                                ::core::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong,
                                b"%Y%m%d%H%M%SZ\0" as *const u8 as *const libc::c_char,
                                tm_0,
                            ) != 0 as libc::c_int as libc::c_ulong
                            {
                                sudo_lbuf_append_v1(
                                    lbuf,
                                    b"    NotAfter: %s\n\0" as *const u8 as *const libc::c_char,
                                    buf_0.as_mut_ptr(),
                                );
                            }
                        }
                        sudo_lbuf_append_v1(
                            lbuf,
                            dcgettext(
                                b"sudoers\0" as *const u8 as *const libc::c_char,
                                b"    Commands:\n\0" as *const u8 as *const libc::c_char,
                                5 as libc::c_int,
                            ),
                        );
                    }
                    sudo_lbuf_append_v1(lbuf, b"\t\0" as *const u8 as *const libc::c_char);
                    sudoers_format_member(
                        lbuf,
                        parse_tree,
                        (*cs).cmnd,
                        b"\n\t\0" as *const u8 as *const libc::c_char,
                        CMNDALIAS,
                    );
                    sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                    prev_cs = cs;
                    nfound += 1;
                    cs = (*cs).entries.tqe_next;
                }
            }
            priv_0 = (*priv_0).entries.tqe_next;
        }

        debug_return_int!(nfound);
    } //unsafe
}

fn sudo_display_userspecs(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut lbuf: *mut sudo_lbuf,
    mut verbose: bool,
) -> libc::c_int {
    let mut us: *mut userspec = std::ptr::null_mut::<userspec>();
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        us = (*parse_tree).userspecs.tqh_first;
        while !us.is_null() {
            if userlist_matches(parse_tree, pw, &(*us).users) == ALLOW {
                if verbose {
                    nfound += display_priv_long(parse_tree, pw, us, lbuf);
                } else {
                    nfound += display_priv_short(parse_tree, pw, us, lbuf);
                }
            }
            us = (*us).entries.tqe_next;
        }
        if sudo_lbuf_error_v1(lbuf) {
            debug_return_int!(-(1 as libc::c_int));
        }
        debug_return_int!(nfound);
    } //unsafe
}

/*
 * Display matching Defaults entries for the given user on this host.
 */
fn display_defaults(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut lbuf: *mut sudo_lbuf,
) -> libc::c_int {
    let mut d: *mut defaults = std::ptr::null_mut::<defaults>();
    let mut prefix: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        if (*lbuf).len == 0 as libc::c_int
            || isspace!(
                *((*lbuf).buf).offset(((*lbuf).len - 1 as libc::c_int) as isize) as libc::c_uchar
                    as libc::c_int as isize
            ) != 0
        {
            prefix = b"    \0" as *const u8 as *const libc::c_char as *mut libc::c_char;
        } else {
            prefix = b", \0" as *const u8 as *const libc::c_char as *mut libc::c_char;
        }

        d = (*parse_tree).defaults.tqh_first;
        while !d.is_null() {
            match (*d).type_0 as libc::c_int {
                DEFAULTS_HOST => {
                    if hostlist_matches(parse_tree, pw, (*d).binding) != ALLOW {
                        d = (*d).entries.tqe_next;
                        continue;
                    }
                }
                DEFAULTS_USER => {
                    if userlist_matches(parse_tree, pw, (*d).binding) != ALLOW {
                        d = (*d).entries.tqe_next;
                        continue;
                    }
                }
                DEFAULTS_RUNAS | DEFAULTS_CMND => {
                    d = (*d).entries.tqe_next;
                    continue;
                }
                _ => {}
            }
            sudo_lbuf_append_v1(lbuf, b"%s\0" as *const u8 as *const libc::c_char, prefix);
            sudoers_format_default(lbuf, d);
            prefix = b", \0" as *const u8 as *const libc::c_char as *mut libc::c_char;
            nfound += 1;
            d = (*d).entries.tqe_next;
        }
        if sudo_lbuf_error_v1(lbuf) {
            debug_return_int!(-(1 as libc::c_int));
        }
        debug_return_int!(nfound);
    } //unsafe
}

/*
 * Display Defaults entries of the given type.
 */
fn display_bound_defaults_by_type(
    mut parse_tree: *mut sudoers_parse_tree,
    mut deftype: libc::c_int,
    mut lbuf: *mut sudo_lbuf,
) -> libc::c_int {
    let mut d: *mut defaults = std::ptr::null_mut::<defaults>();
    let mut binding: *mut member_list = std::ptr::null_mut::<member_list>();
    let mut m: *mut member = std::ptr::null_mut::<member>();
    let mut dsep: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut atype: libc::c_int = 0;
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        match deftype {
            DEFAULTS_HOST => {
                atype = HOSTALIAS;
                dsep = b"@\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
            }
            DEFAULTS_USER => {
                atype = USERALIAS;
                dsep = b":\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
            }
            DEFAULTS_RUNAS => {
                atype = RUNASALIAS;
                dsep = b">\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
            }
            DEFAULTS_CMND => {
                atype = CMNDALIAS;
                dsep = b"!\0" as *const u8 as *const libc::c_char as *mut libc::c_char;
            }
            _ => {
                debug_return_int!(-(1 as libc::c_int));
            }
        }
        d = (*parse_tree).defaults.tqh_first;
        while !d.is_null() {
            if (*d).type_0 as libc::c_int == deftype {
                nfound += 1;
                if binding != (*d).binding {
                    binding = (*d).binding;
                    if nfound != 1 as libc::c_int {
                        sudo_lbuf_append_v1(lbuf, b"\n\0" as *const u8 as *const libc::c_char);
                    }
                    sudo_lbuf_append_v1(
                        lbuf,
                        b"    Defaults%s\0" as *const u8 as *const libc::c_char,
                        dsep,
                    );
                    m = (*binding).tqh_first;
                    while !m.is_null() {
                        if m != (*binding).tqh_first {
                            sudo_lbuf_append_v1(lbuf, b",\0" as *const u8 as *const libc::c_char);
                        }
                        sudoers_format_member(
                            lbuf,
                            parse_tree,
                            m,
                            b", \0" as *const u8 as *const libc::c_char,
                            atype,
                        );
                        sudo_lbuf_append_v1(lbuf, b" \0" as *const u8 as *const libc::c_char);
                        m = (*m).entries.tqe_next;
                    }
                } else {
                    sudo_lbuf_append_v1(lbuf, b", \0" as *const u8 as *const libc::c_char);
                }
                sudoers_format_default(lbuf, d);
            }
            d = (*d).entries.tqe_next;
        }

        if sudo_lbuf_error_v1(lbuf) {
            debug_return_int!(-(1 as libc::c_int));
        }
        debug_return_int!(nfound);
    } //unsafe
}

/*
 * Display Defaults entries that are per-runas or per-command
 */
fn display_bound_defaults(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut lbuf: *mut sudo_lbuf,
) -> libc::c_int {
    let mut nfound: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        /* XXX - should only print ones that match what the user can do. */
        nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_RUNAS, lbuf);
        nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_CMND, lbuf);

        if sudo_lbuf_error_v1(lbuf) {
            debug_return_int!(-(1 as libc::c_int));
        }
        debug_return_int!(nfound);
    }
}

unsafe extern "C" fn output(mut buf: *const libc::c_char) -> libc::c_int {
    let mut msg: sudo_conv_message = sudo_conv_message {
        msg_type: 0,
        timeout: 0,
        msg: std::ptr::null::<libc::c_char>(),
    };
    let mut repl: sudo_conv_reply = sudo_conv_reply {
        reply: std::ptr::null_mut::<libc::c_char>(),
    };
    debug_decl!(SUDOERS_DEBUG_PARSER!());

    /* Call conversation function */
    memset(
        &mut msg as *mut sudo_conv_message as *mut libc::c_void,
        0 as libc::c_int,
        ::core::mem::size_of::<sudo_conv_message>() as libc::c_ulong,
    );
    msg.msg_type = SUDO_CONV_INFO_MSG;
    msg.msg = buf;
    memset(
        &mut repl as *mut sudo_conv_reply as *mut libc::c_void,
        0 as libc::c_int,
        ::core::mem::size_of::<sudo_conv_reply>() as libc::c_ulong,
    );
    if sudo_conv.expect("non-null function pointer")(
        1 as libc::c_int,
        &mut msg as *mut sudo_conv_message as *const sudo_conv_message,
        &mut repl,
        std::ptr::null_mut::<sudo_conv_callback>(),
    ) == -(1 as libc::c_int)
    {
        debug_return_int!(0);
    }

    debug_return_int!(strlen(buf) as libc::c_int);
}

/*
 * Print out privileges for the specified user.
 * Returns true on success or -1 on error.
 */
#[no_mangle]
pub fn display_privs(
    mut snl: *mut sudo_nss_list,
    mut pw: *mut passwd,
    mut verbose: bool,
) -> libc::c_int {
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut def_buf: sudo_lbuf = sudo_lbuf {
        output: None,
        buf: std::ptr::null_mut::<libc::c_char>(),
        continuation: std::ptr::null::<libc::c_char>(),
        indent: 0,
        len: 0,
        size: 0,
        cols: 0,
        error: 0,
    };
    let mut priv_buf: sudo_lbuf = sudo_lbuf {
        output: None,
        buf: std::ptr::null_mut::<libc::c_char>(),
        continuation: std::ptr::null::<libc::c_char>(),
        indent: 0,
        len: 0,
        size: 0,
        cols: 0,
        error: 0,
    };
    let mut sb: stat = sb_all_arch;
    let mut cols: libc::c_int = 0;
    let mut count: libc::c_int = 0;
    let mut olen: libc::c_int = 0;
    let mut n: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        cols = sudo_user.cols;
        if fstat(STDOUT_FILENO, &mut sb) == 0 as libc::c_int && S_ISFIFO!(sb.st_mode) {
            cols = 0;
        }
        sudo_lbuf_init_v1(
            &mut def_buf,
            Some(output as unsafe extern "C" fn(*const libc::c_char) -> libc::c_int),
            4 as libc::c_int,
            std::ptr::null::<libc::c_char>(),
            cols,
        );
        sudo_lbuf_init_v1(
            &mut priv_buf,
            Some(output as unsafe extern "C" fn(*const libc::c_char) -> libc::c_int),
            8 as libc::c_int,
            std::ptr::null::<libc::c_char>(),
            cols,
        );

        sudo_lbuf_append_v1(
            &mut def_buf as *mut sudo_lbuf,
            dcgettext(
                b"sudoers\0" as *const u8 as *const libc::c_char,
                b"Matching Defaults entries for %s on %s:\n\0" as *const u8 as *const libc::c_char,
                5 as libc::c_int,
            ),
            (*pw).pw_name,
            sudo_user.srunhost,
        );
        count = 0 as libc::c_int;
        'bad: loop {
            nss = (*snl).tqh_first;
            while !nss.is_null() {
                n = display_defaults((*nss).parse_tree, pw, &mut def_buf);
                if n == -(1 as libc::c_int) {
                    break 'bad;
                }
                count += n;
                nss = (*nss).entries.tqe_next;
            }
            if count != 0 as libc::c_int {
                sudo_lbuf_append_v1(
                    &mut def_buf as *mut sudo_lbuf,
                    b"\n\n\0" as *const u8 as *const libc::c_char,
                );
            } else {
                /* Undo Defaults header. */
                def_buf.len = 0 as libc::c_int;
            }

            /* Display Runas and Cmnd-specific defaults. */
            olen = def_buf.len;
            sudo_lbuf_append_v1(
                &mut def_buf as *mut sudo_lbuf,
                dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"Runas and Command-specific defaults for %s:\n\0" as *const u8
                        as *const libc::c_char,
                    5 as libc::c_int,
                ),
                (*pw).pw_name,
            );
            count = 0 as libc::c_int;
            nss = (*snl).tqh_first;
            while !nss.is_null() {
                n = display_bound_defaults((*nss).parse_tree, pw, &mut def_buf);
                if n == -(1 as libc::c_int) {
                    break 'bad;
                }
                count += n;
                nss = (*nss).entries.tqe_next;
            }
            if count != 0 as libc::c_int {
                sudo_lbuf_append_v1(
                    &mut def_buf as *mut sudo_lbuf,
                    b"\n\n\0" as *const u8 as *const libc::c_char,
                );
            } else {
                /* Undo Defaults header. */
                def_buf.len = olen;
            }

            /* Display privileges from all sources. */
            sudo_lbuf_append_v1(
                &mut priv_buf as *mut sudo_lbuf,
                dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"User %s may run the following commands on %s:\n\0" as *const u8
                        as *const libc::c_char,
                    5 as libc::c_int,
                ),
                (*pw).pw_name,
                sudo_user.srunhost,
            );
            count = 0 as libc::c_int;
            nss = (*snl).tqh_first;
            while !nss.is_null() {
                if ((*nss).query).expect("non-null function pointer")(nss, pw)
                    != -(1 as libc::c_int)
                {
                    n = sudo_display_userspecs((*nss).parse_tree, pw, &mut priv_buf, verbose);
                    if n == -(1 as libc::c_int) {
                        break 'bad;
                    }
                    count += n;
                }
                nss = (*nss).entries.tqe_next;
            }

            if count == 0 as libc::c_int {
                def_buf.len = 0 as libc::c_int;
                priv_buf.len = 0 as libc::c_int;
                sudo_lbuf_append_v1(
                    &mut priv_buf as *mut sudo_lbuf,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"User %s is not allowed to run sudo on %s.\n\0" as *const u8
                            as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                    (*pw).pw_name,
                    sudo_user.srunhost,
                );
            }
            if sudo_lbuf_error_v1(&mut def_buf) as libc::c_int != 0
                || sudo_lbuf_error_v1(&mut priv_buf) as libc::c_int != 0
            {
                break 'bad;
            }

            sudo_lbuf_print_v1(&mut def_buf);
            sudo_lbuf_print_v1(&mut priv_buf);

            sudo_lbuf_destroy_v1(&mut def_buf);
            sudo_lbuf_destroy_v1(&mut priv_buf);

            debug_return_int!(true as libc::c_int);
        }

        //bad:
        sudo_lbuf_destroy_v1(&mut def_buf);
        sudo_lbuf_destroy_v1(&mut priv_buf);

        debug_return_int!(-(1 as libc::c_int));
    } //unsafe
}

fn display_cmnd_check(
    mut parse_tree: *mut sudoers_parse_tree,
    mut pw: *mut passwd,
    mut now: time_t,
) -> libc::c_int {
    let mut host_match: libc::c_int = 0;
    let mut runas_match: libc::c_int = 0;
    let mut cmnd_match: libc::c_int = 0;
    let mut cs: *mut cmndspec = std::ptr::null_mut::<cmndspec>();
    let mut priv_0: *mut privilege = std::ptr::null_mut::<privilege>();
    let mut us: *mut userspec = std::ptr::null_mut::<userspec>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        us = *(*((*parse_tree).userspecs.tqh_last as *mut userspec_list)).tqh_last;
        while !us.is_null() {
            if userlist_matches(parse_tree, pw, &(*us).users) != ALLOW {
                us = *(*((*us).entries.tqe_prev as *mut userspec_list)).tqh_last;
                continue;
            }
            priv_0 = *(*((*us).privileges.tqh_last as *mut privilege_list)).tqh_last;
            while !priv_0.is_null() {
                host_match = hostlist_matches(parse_tree, pw, &(*priv_0).hostlist);
                if host_match != ALLOW {
                    priv_0 = *(*((*priv_0).entries.tqe_prev as *mut privilege_list)).tqh_last;
                    continue;
                }
                cs = *(*((*priv_0).cmndlist.tqh_last as *mut cmndspec_list)).tqh_last;
                while !cs.is_null() {
                    if (*cs).notbefore != UNSPEC as libc::c_long && now < (*cs).notbefore {
                        cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                        continue;
                    }

                    /*if (*cs).notbefore != UNSPEC as libc::c_long {
                        if now < (*cs).notbefore {
                            cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                            continue;
                        }
                    }*/
                    if (*cs).notafter != UNSPEC as libc::c_long && now > (*cs).notafter {
                        cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                        continue;
                    }

                    /*if (*cs).notafter != UNSPEC as libc::c_long {
                        if now > (*cs).notafter {
                            cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                            continue;
                        }
                    }*/
                    runas_match = runaslist_matches(
                        parse_tree,
                        (*cs).runasuserlist,
                        (*cs).runasgrouplist,
                        std::ptr::null_mut::<*mut member>(),
                        std::ptr::null_mut::<*mut member>(),
                    );
                    if runas_match == ALLOW {
                        cmnd_match = cmnd_matches(parse_tree, (*cs).cmnd);
                        if cmnd_match != UNSPEC {
                            debug_return_int!(cmnd_match);
                        }
                    }
                    cs = *(*((*cs).entries.tqe_prev as *mut cmndspec_list)).tqh_last;
                }
                priv_0 = *(*((*priv_0).entries.tqe_prev as *mut privilege_list)).tqh_last;
            }
            us = *(*((*us).entries.tqe_prev as *mut userspec_list)).tqh_last;
        }
        debug_return_int!(UNSPEC);
    } //unsafe
}

/*
 * Check user_cmnd against sudoers and print the matching entry if the
 * command is allowed.
 * Returns true if the command is allowed, false if not or -1 on error.
 */
#[no_mangle]
pub fn display_cmnd(mut snl: *mut sudo_nss_list, mut pw: *mut passwd) -> libc::c_int {
    let mut nss: *mut sudo_nss = std::ptr::null_mut::<sudo_nss>();
    let mut m: libc::c_int = 0;
    let mut match_0: libc::c_int = -(1 as libc::c_int);
    let mut ret: libc::c_int = 0 as libc::c_int;
    let mut now: time_t = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());

        /* Iterate over each source, checking for the command. */
        time(&mut now);
        nss = (*snl).tqh_first;
        while !nss.is_null() {
            if ((*nss).query).expect("non-null function pointer")(nss, pw) == -(1 as libc::c_int) {
                /* The query function should have printed an error message. */
                debug_return_int!(-(1 as libc::c_int));
            }

            m = display_cmnd_check((*nss).parse_tree, pw, now);
            if m != UNSPEC {
                match_0 = m;
            }

            if !sudo_nss_can_continue(nss, m) {
                break;
            }
            nss = (*nss).entries.tqe_next;
        }
        if match_0 == ALLOW {
            let len: libc::c_int = sudo_printf.expect("non-null function pointer")(
                SUDO_CONV_INFO_MSG,
                b"%s%s%s\n\0" as *const u8 as *const libc::c_char,
                sudo_user.cmnd_safe,
                if !(sudo_user.cmnd_args).is_null() {
                    b" \0" as *const u8 as *const libc::c_char
                } else {
                    b"\0" as *const u8 as *const libc::c_char
                },
                if !(sudo_user.cmnd_args).is_null() {
                    sudo_user.cmnd_args as *const libc::c_char
                } else {
                    b"\0" as *const u8 as *const libc::c_char
                },
            );
            ret = if len < 0 as libc::c_int {
                -(1 as libc::c_int)
            } else {
                true as libc::c_int
            };
        }

        debug_return_int!(ret);
    } //unsafe
}
